package com.service.login.controller;


import com.service.config.annotation.Distinct;
import com.service.config.utils.*;
import com.service.login.dto.*;
import com.service.login.entity.UserInfo;
import com.service.login.service.UserExtendService;
import com.service.login.service.UserInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import io.swagger.annotations.ApiParam;
import org.apache.el.lang.ELArithmetic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.service.config.constant.Constant.*;

/**
 * 用户表(UserInfo)表控制层
 *
 * @author makejava
 * @since 2021-03-30 11:37:22
 */
@CrossOrigin
@RestController
@RequestMapping("userInfo")
@Api(value = "用户 ")
public class UserInfoController {
    /**
     * 服务对象
     */
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    RedisTemplate redisTemplate;
    @Resource
    private UserExtendService userExtendService;
    /**
     * 统一登录
     *
     * @param
     * @return
     */
    @PostMapping(value = "auth",produces="application/json")
    @ApiOperation(value = "统一登录")
    @ResponseBody
    public Result loginManage(HttpServletRequest httpServletRequest, @RequestBody LoginUserDto loginUserDto,
                              @RequestParam("serviceId") String serviceId) throws Exception {
        HashMap map = new HashMap();
        if(loginUserDto.getAccount() == null || "".equals(loginUserDto.getAccount())
                || "".equals(loginUserDto.getPassword()) || loginUserDto.getPassword() == null){
            return Result.failure(10003,"用户名或密码为空");
        }
        map = userInfoService.getToken(loginUserDto,serviceId,httpServletRequest);
        if(map == null){
            return Result.failure(USER_NOT_FOUND,"用户不存在");
        }
        return Result.ok().setData(map);

    }
    /**
     * 用户标准注册
     *
     * @param
     * @return
     */
    @PostMapping(value = "register",produces="application/json")
    @ApiOperation(value = "用户标准注册")
    @ResponseBody
    //@Distinct
    public Result register(HttpServletRequest httpServletRequest,@RequestBody UserInfoDto userInfoDto,
                           @RequestParam(value = "serviceId") String serviceId) throws Exception {
        if(userInfoDto.getUsername() == null || "".equals(userInfoDto.getUsername())
                || "".equals(userInfoDto.getPassword()) || userInfoDto.getPassword() == null){
            return Result.failure(USERNAME_OR_NOTFOUND,"用户名或密码为空,请重新输入");
        }
        String realIp = getRealIp(httpServletRequest);
        HashMap map = new HashMap();
        UserInfo register = new UserInfo();
        if (serviceId.equals("2")) {
            register = userInfoService.mspRegister(userInfoDto,realIp);
        }else {
            register = userInfoService.register(userInfoDto,realIp);
        }
        if (register != null) {
            String token = UserTokenManager.generateToken(register.getId());
            map.put("Token",token);
            UserDto userDto = ModelMapperUtil.strictMap(userInfoDto, UserDto.class);
            userDto.setIp(realIp); // 来源ip
            userDto.setDate(new Date()); //登录时间
            redisUtil.setValue(token+register.getId(), JsonXMLUtils.obj2json(register)); // 存入缓存
            return Result.ok().setData(map);
        } else {
            return  Result.failure(USERNAME_REPEAT,"用户名已存在，请重新输入");
        }
    }
    /**
     * 用户简化注册
     *
     * @param
     * @return
     */
    @PostMapping(value = "simplifyRegister",produces="application/json")
    @ApiOperation(value = "用户简化注册")
    @ResponseBody
    //@Distinct
    public Result simplifyRegister(HttpServletRequest httpServletRequest,@RequestBody SimplifyUserInfoDto simplifyUserInfoDto,
                           @RequestParam(value = "serviceId") String serviceId) throws Exception {
        if(simplifyUserInfoDto.getApiUsername() == null || "".equals(simplifyUserInfoDto.getApiUsername())
                || "".equals(simplifyUserInfoDto.getApiPassword()) || simplifyUserInfoDto.getApiPassword() == null){
            return Result.failure(USERNAME_OR_NOTFOUND,"用户名或密码为空,请重新输入");
        }
        String realIp = getRealIp(httpServletRequest);
        HashMap map = new HashMap();
        UserInfo register = new UserInfo();
        if (serviceId.equals("2")) {
            Result result = userInfoService.MspSimplifyRegister(simplifyUserInfoDto,realIp);
            return result;
        }else {
            Result result = userInfoService.simplifyRegister(simplifyUserInfoDto, realIp);
            return result;
        }
    }
    /**
     * 忘记密码/修改密码
     *
     * @param
     * @return
     */
    @PostMapping(value = "retrieve",produces="application/json")
    @ApiOperation(value = "忘记密码/修改密码")
    @ResponseBody
    public Result retrieve(@RequestHeader(value = "cloud-Auth-Token",required = false) String cloudAuthToken,
                           @RequestBody UserInfoDto userInfoDto,
                           @RequestParam("serviceId") String serviceId) throws Exception {
        if (cloudAuthToken != null && !cloudAuthToken.equals("")) {
            String userId = UserTokenManager.getUserId(cloudAuthToken);
            if (redisUtil.exist(cloudAuthToken+userId)) { // 密码修改
                userInfoDto.setId(userId);
                if (serviceId.equals("2")) { // msp服务修改密码
                    userInfoService.updateMsp(ModelMapperUtil.strictMap(userInfoDto, UserInfo.class));
                }else { // 默认大屏服务修改密码
                    userInfoService.update(ModelMapperUtil.strictMap(userInfoDto, UserInfo.class));
                }
                Set<String> strings = redisUtil.redisLike(userId);
                clearCache(strings, redisUtil);
                return Result.ok();
            }else {
                return Result.failure(USERNAME_Off_SITE,usernameOffSite);
            }
        }
        UserInfo userInfo = new UserInfo();
        if (serviceId.equals("2")) { // msp服务修改密码
            userInfo = userInfoService.queryByMspUserName(userInfoDto);
        }else { // 默认大屏服务修改密码
            userInfo =  userInfoService.queryByUserName(userInfoDto);
        }
        if (userInfo == null) {
            return Result.failure(USER_INFO_IMPERFECT,"用户信息不完善请联系管理人员进行修正");
        }
        return Result.ok();
    }

    /**
     * 清除缓存
     * @param strings
     * @param redisUtil
     */
    public static void clearCache(Set<String> strings, RedisUtil redisUtil) {
        strings.stream().forEach(
            s -> {
                String value = redisUtil.getValue(s);
                try {
                    UserDto userDto1 = JsonXMLUtils.json2obj(value, UserDto.class);
                    userDto1.setOffTime(new Date());
                    long dateMin = DateUtil.getDateMin(DateUtil.datetoString(userDto1.getDate()), DateUtil.datetoString(new Date()));
                    userDto1.setOnlineTime(dateMin); // 在线时长
                    redisUtil.leftPush(USER_INFO,JsonXMLUtils.obj2json(userDto1));
                    redisUtil.delete(s);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        );
    }

    /**
     * 找回密码
     *
     * @param
     * @return
     */
    @PostMapping(value = "verification",produces="application/json")
    @ApiOperation(value = "找回密码")
    @ResponseBody
    public Result retrieve(@RequestBody VerificationCodeDto verificationCodeDto,
                           @RequestParam("serviceId") String serviceId) throws Exception {
        if (redisUtil.exist(verificationCodeDto.getCode())) {
            if (verificationCodeDto.getUsername() != null && !verificationCodeDto.getUsername().equals("")) {
                String value = redisUtil.getValue(verificationCodeDto.getCode());
                UserInfoDto userInfoDto =JsonXMLUtils.json2obj(value, UserInfoDto.class);
                if (verificationCodeDto.getUsername().equals(userInfoDto.getUsername())) {
                    UserInfo userInfo = JsonXMLUtils.json2obj(value, UserInfo.class);
                    userInfo.setPassword(verificationCodeDto.getPassword());
                    if (serviceId.equals("2")) { // msp服务修改密码
                        userInfoService.updateMsp(ModelMapperUtil.strictMap(userInfoDto, UserInfo.class));
                    }else { // 默认大屏服务修改密码
                        userInfoService.update(ModelMapperUtil.strictMap(userInfoDto, UserInfo.class));
                    }
                    redisUtil.delete(verificationCodeDto.getCode());
                    return Result.ok();
                }else {
                    return Result.failure(USERNAME_DIFFERENT,"用户名不正确，请重新填写");
                }
            }else {
                return Result.failure(USER_NOT_FOUND,"用户名不存在");
            }
        }
        return Result.failure(CODE_INVALID,"验证码已失效，请重新获取");
    }




    /**
     * 用户注销
     *
     * @param
     * @return
     */
    @GetMapping(value = "loginOut",produces="application/json")
    @ApiOperation(value = "用户注销")
    @ResponseBody
    public Result loginOut(@RequestHeader(value = "cloud-Auth-Token",required = false) String cloudAuthToken) throws Exception {
        if (cloudAuthToken != null && !cloudAuthToken.equals("")) {
            String userId = UserTokenManager.getUserId(cloudAuthToken);
            if (redisUtil.exist(cloudAuthToken+userId)) { // 缓存是否存在
                String value = redisUtil.getValue(cloudAuthToken + userId);
                UserDto userDto = JsonXMLUtils.json2obj(value, UserDto.class);
                userDto.setOffTime(new Date());
                userDto.setOnlineTime(DateUtil.getDateMin(DateUtil.datetoString(userDto.getDate()), DateUtil.datetoString(new Date())));
                UserInfo userInfo = new UserInfo();
                userInfo.setId(userId);
                userInfo.setIp(userDto.getIp());
                userInfo.setOnlineTime(userDto.getOnlineTime());
                userInfo.setOffTime(userDto.getOffTime());
                userInfo.setStatus("1");
                userInfoService.update(userInfo);
                redisUtil.leftPush(USER_INFO,JsonXMLUtils.obj2json(userDto));
                redisUtil.delete(cloudAuthToken+userId);
                return Result.ok();
            }else {
                return Result.failure(USERNAME_Off_SITE,usernameOffSite);
            }
        }else {
            return Result.failure(USER_NOT_LOGIN,"用户未登录");
        }
    }
    public String getRealIp(HttpServletRequest request) {
        return getString(request);

    }

    public static String getString(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        ip = getString(request, ip);
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static String getString(HttpServletRequest request, String ip) {
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        return ip;
    }

    /**
     * 查询在线用户
     *
     * @param
     * @return
     */
    @GetMapping(value = "queryOnlineUser",produces="application/json")
    @ApiOperation(value = "查询在线用户")
    @ResponseBody
    public Result queryOnlineUser()  {
        List<UserInfo> userInfos = userInfoService.queryAllByLimit(0,999999);
        List<UserDto> userDtoArrayList = new ArrayList<>();
        userInfos.forEach(userInfo -> {
            Set<String> strings= redisUtil.redisLike(userInfo.getId());
            if (strings != null){
                strings.stream().forEach(s -> {
                    String value = redisUtil.getValue(s);
                    try {
                        UserDto userDto = JsonXMLUtils.json2obj(value, UserDto.class);
                        long dateMin = DateUtil.getDateMin(DateUtil.datetoString(userDto.getDate()), DateUtil.datetoString(new Date()));
                        userDto.setOnlineTime(dateMin);
                        userDtoArrayList.add(userDto);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                });

            }
        });
        return Result.ok().setData(userDtoArrayList);
    }
    /**
     * 点击账号名可查询用户个人信息
     *
     * @param
     * @return
     */
    @GetMapping(value = "queryOnlineByUser",produces="application/json")
    @ApiOperation(value = "查询用户个人信息")
    @ResponseBody
    public Result queryOnlineByUser(@RequestParam("userId") String userId,
                                    @RequestParam("serviceId") String serviceId)  {
        if (serviceId.equals("2")) {
            UserExtendDto userExtendDto  = userExtendService.queryByMspUserId(userId);
            return Result.ok().setData(userExtendDto);
        }else {
            UserExtendDto userExtendDto = userExtendService.queryByUserId(userId);
            return Result.ok().setData(userExtendDto);
        }
    }
    /**
     * 用户踢下线
     *
     * @param
     * @return
     */
    @GetMapping(value = "offLine",produces="application/json")
    @ApiOperation(value = "用户踢下线")
    @ResponseBody
    public Result queryOnlineUser(@RequestParam("userId") String userId)  {
        Set<String> strings= redisUtil.redisLike(userId);
        clearCache(strings,redisUtil);
        return Result.ok();
    }
    /**
     * 查询所有用户
     *
     * @param
     * @return
     */
    @GetMapping(value = "queryAllUser",produces="application/json")
    @ApiOperation(value = "查询所有用户")
    @ResponseBody
    public Result queryAllUser()  {
        List<UserInfo> userInfos = userInfoService.queryAllByLimit(0,999999);
        return Result.ok().setData(ModelMapperUtil.strictMapList(userInfos,UserDto.class));
    }
}
